package com.darwin.darwinIsometric.core
{
	import com.darwin.darwinBitmapEngine.core.ContainerNode;
	import com.darwin.darwinIsometric.core.isoConst.IsoType;
	import com.darwin.darwinIsometric.utils.IsoUtils;
	
	import flash.geom.Point;
	
	/**
	 * 
	 * 2.5D世界对象
	 * @创建： lipi
	 */
	public class IsoObject extends ContainerNode
	{
		
		public function IsoObject(floorWidth:Number,floorHeight:Number)
		{
			super();
//			var cube:Cube = new Cube(16,16);
//			var bitmapData:BitmapData = BitmapDataTool.getBitmapData(cube);
//			var node:Node = new Node(bitmapData);
//			addNode(node); 
			
			_floorWidth = floorWidth;
			_floorHeight = floorHeight;
			
		}
		
		
		/**
		 * 根据 x3d,y3d,z3d,offsetX,offsetY计算得出IsoObject的2D坐标，
		 * 2D坐标用于渲染
		 */
		private function createXY():void
		{
			var $point:Point = IsoUtils.isoToScreen(new Point3D(x3d,y3d,z3d));
			this.x = $point.x + offsetX;
			this.y = $point.y + offsetY;
			statusChangeMark();
			
			_isoPositionChanged = true;
		}
		
		
		private var _offsetX:Number = 0;
		/**
		 * 2D图形相对于2.5D原点的偏移量
		 */
		public function get offsetX():Number
		{
			return _offsetX;
		}

		public function set offsetX(value:Number):void
		{
			_offsetX = value;
			createXY();
		}

		private var _offsetY:Number = 0;

		/**
		 * 2D图形相对于2.5D原点的偏移量
		 */
		public function get offsetY():Number
		{
			return _offsetY;
		}

		public function set offsetY(value:Number):void
		{
			_offsetY = value;
			createXY();
		}
		
		private var _type:String = IsoType.OBJECT;
		/**
		 * 对像类别，IsoType.FLOOR 或 IsoType.OBJECT,默认为IsoType.OBJECT。
		 * 添加到IsoWorld后改变这个值将导致不正常
		 */
		public function get isoType():String
		{
			return _type;
		}
		public function set isoType(value:String):void
		{
			_type = value;
		}
		
		
		private var _simple:Boolean = false;

		/**
		 * 简单的对象，不参与占位的
		 */
		public function get simple():Boolean
		{
			return _simple;
		}

		public function set simple(value:Boolean):void
		{
			_simple = value;
		}
		
		
		
		
		private var _direction:int = 0;
		/**
		 * 物体的方向,可选值为 45 90 135 180 225 270 315,默认为0面对Z轴方向,旋转为顺时针
		 */
		public function set direction(value:int):void
		{
			_direction = value;
		}
		public function get direction():int
		{
			return _direction;
		}
		
		private var _allowableDirection:int = 0;
		
		/**
		 * 允许的物体方向， <br/>
		 * 1:只有一种方向,不可转动;<br/>
		 * 2:可以有0 和270;<br/>
		 * 4:0 90 180 270;<br/>
		 * 8:八方向;<br/>
		 * @return 
		 */
		public function get allowableDirection():int
		{
			return _allowableDirection;
		}
		public function set allowableDirection(v:int):void
		{
			_allowableDirection = v;
		}
		
		
		
		private var _floorWidth:Number;
		/**
		 * 物件底部的宽，floorWidth表示在x方向底部所占用的宽度
		 * @return 
		 */
		public function get floorWidth():Number
		{
			return _floorWidth;
		}
		
		public function set floorWidth(value:Number):void
		{
			_floorWidth = value;
			statusChangeMark();
			_isoPositionChanged = true;
		}
		
		private var _floorHeight:Number;
		/**
		 * 物件底部的高，floorHeight表示在z方向底部所占用的宽度
		 * @return 
		 */
		public function get floorHeight():Number
		{
			return _floorHeight;
		}

		public function set floorHeight(value:Number):void
		{
			_floorHeight = value;
			statusChangeMark();
			_isoPositionChanged = true;
		}

		private var _verticalHeight:Number = 0;
		/**
		 * 物件的立体高度，verticalHeight表示在y方向物件所点用高度
		 * @return 
		 * 
		 */
		public function get verticalHeight():Number
		{
			return _verticalHeight;
		}

		public function set verticalHeight(value:Number):void
		{
			_verticalHeight = value;
		}
		
		
		
		
		private var _x3d:Number = 0;

		/**
		 * 2.5D x坐标，x增大物件朝屏幕右下角移动
		 * @return 
		 */
		public function get x3d():Number
		{
			return _x3d;
		}

		public function set x3d(value:Number):void
		{
			clearUp();
			_x3d = value;
			createXY();
		}
		
		
		private var _y3d:Number = 0;

		/**
		 * 2.5D y坐标，y减小物件朝屏幕正上方移动
		 * @return 
		 */
		public function get y3d():Number
		{
			return _y3d;
		}

		public function set y3d(value:Number):void
		{
			clearUp();
			_y3d = value;
			createXY();
		}

		
		private var _z3d:Number = 0;

		/**
		 * 2.5D z坐标，z增大物件朝屏幕
		 * @return 
		 */
		public function get z3d():Number
		{
			return _z3d;
		}

		public function set z3d(value:Number):void
		{
			clearUp();
			_z3d = value;
			createXY();
		}
		
		/**
		 * 通过格子坐标设置位置（注意，如果isoObject没被添加到舞台这个方法的坐标可能不准确）
		 * @param isoPosition
		 */
		public function setPosition3D(isoPosition:IsoPosition):void
		{
			x3d = isoPosition.x * size;
			z3d = isoPosition.z * size;
		}
		

		/**
		 * 2.5D 物件坐标 
		 */
		public function get postion3D():Point3D
		{
			return new Point3D(x3d,y3d,z3d);
		}

		/**
		 * @private
		 */
		public function set postion3D(value:Point3D):void
		{
			clearUp();
			_x3d = value.x;
			_y3d = value.y;
			_z3d = value.z;
			createXY();
		}
		
		private function clearUp():void
		{
			if(this.parentWorld)
			{
				this.parentWorld.clearUpIsoObject(this,true);
			}
		}
		
		//计算当前对象所在的网格位置
		private function countPosition():void
		{
			if(_isoPositionChanged)
			{
				var $isox:int = Math.floor(this.x3d / _size);
				var $isoz:int = Math.floor(this.z3d / _size);
				
				var $isomx:int = Math.floor((this.x3d + this.floorWidth-1) / _size);
				var $isomz:int = Math.floor((this.z3d + this.floorHeight-1) / _size);
				
				_middleX = this.floorWidth/2 + this.x3d;
				_middleZ = this.floorHeight/2 + this.z3d;
				
				_isoPosition = new IsoPosition($isox,$isoz);
				_maxIsoPosition = new IsoPosition($isomx,$isomz);
				_isoPositionChanged = false;
			}
		}
		
		
		
		private var _middleX:Number = 0;
		/**
		 * 获得占地中心点的x坐标，如果对象是长条形取得的坐标位置可能会不准确
		 * 
		 */
		public function get middleX():Number
		{
			countPosition();
			return _middleX;
		}
		
		
		private var _middleZ:Number = 0;
		/**
		 * 获得占地中心点的y坐标，如果对象是长条形取得的坐标位置可能会不准确
		 */
		public function get middleZ():Number
		{
			countPosition();
			return _middleZ;
		}
		
		/**
		 *	获得排序用索引值 
		 * @return 
		 * 
		 */
		public function get sortIndex():Number
		{
			var mid:Point = new Point(floorWidth/2+x3d,floorHeight/2+z3d);
			var indexH:int = layerIndex;
			var indexM:int = mid.x/_size + mid.y/_size;
			var indexL:int = mid.x/_size;
			var indexY:int = (2500-y3d) + gridIndex;
//			var index:Number =indexH*1000000*1000000 + indexM*1000000+ indexL + indexY/10000;
			var index:Number =indexH*1000*1000*10000 + indexM*1000*10000+ indexL*10000 + indexY;
			return index;
		}
		
		private var _gridIndex:int = 0;

		/**
		 *	单个单元格的优先排序索引
		 * <br/>排序优先级等同于y3d属性 ，与y3d不同的是它不会改变物件在场景上的高度
		 */
		public function get gridIndex():int
		{
			return _gridIndex;
		}

		/**
		 * @private
		 */
		public function set gridIndex(value:int):void
		{
			_gridIndex = value;
		}

		
		private var _isoPositionChanged:Boolean = true;
		
		
		private var _isoPosition:IsoPosition;

		/**
		 * 获得等角对象所占用格子中最靠近原点的isoPosition值，isoPosition是基于网格计算的坐标值
		 * @return 
		 */
		public function get isoPosition():IsoPosition
		{
			countPosition();
			return _isoPosition;
		}

		
		private var _maxIsoPosition:IsoPosition;
		
		/**
		 * 获得等角对象所占用格子中最远离原点的isoPosition值，isoPosition是基于网格计算的坐标值
		 * @return 
		 */
		public function get maxIsoPosition():IsoPosition
		{
			countPosition();
			return _maxIsoPosition
		}
		
		
		private var _layerIndex:int = 0;

		/**
		 * 优先排序属性，layerIndex取值范围为0到20。如果layerIndex被设置则排序会优先考虑layerIndex属性。
		 * layerIndex属性通常用在有多层地板的情况下使用，通过layerIndex属性可以使土地始终盖着草皮
		 * <b>注意：动态改变layerIndex不会立即影响物件在场景中的排序</b>
		 */
		public function get layerIndex():int
		{
			return _layerIndex;
		}

		public function set layerIndex(value:int):void
		{
			_layerIndex = value;
		}
		
		private var _isContainer:Boolean = false;
		/**
		 * 表示这个物体上面是否可以放置其它物体,isContainer等于true则可以放置
		 */
		public function set isContainer(value:Boolean):void
		{
			_isContainer = value;
		}
		public function get isContainer():Boolean
		{
			return _isContainer;
		}
		
		private var _canPlaced:Boolean = false;
		/**
		 * 表示这个物体是否可以放置在其它物体上面，canPlaced等于true则可以被放置
		 */
		public function set canPlaced(value:Boolean):void
		{
			_canPlaced = value;
		}
		public function get canPlaced():Boolean
		{
			return _canPlaced;
		}
		
		
		private var _isCombo:Boolean = false;
		/**
		 * 是否结合物，结合物如围栏当放置一起会自动拼合的物体
		 */
		public function set isCombo(v:Boolean):void
		{
			_isCombo = v;
		}
		public function get isCombo():Boolean
		{
			return _isCombo;
		}
		
		private var _comboRim:String = "1111";
		/**
		 * isCombo=true对象边的描述
		 * @return length为4字符串,如'1101'
		 */
		public function get comboRim():String
		{
			return _comboRim;
		}
		public function set comboRim(v:String):void
		{
			_comboRim = v;
		}
		
		
		private var _afloat:Boolean = false;
		/**
		 * 可以飘在空中的，即y值可不依赖其它物体的
		 */
		public function set afloat(value:Boolean):void
		{
			_afloat = value;
		}
		public function get afloat():Boolean
		{
			return _afloat;
		}
		
		private var _allowDIY:int = 1;
		
		/**
		 * 允许DIY
		 * @return 0 1 或者2, 0为不可DIY,1 为允许,2为需条件满足
		 */
		public function get allowDIY():int
		{
			return _allowDIY;
		}
		public function set allowDIY(v:int):void
		{
			_allowDIY = v;
		}
		
		
		
		
		
		private var _size:int = 16;
		/**
		 *	 所在世界每格子大小
		 */
		public function get size():int
		{
			return _size;
		}
		
		private var _walkable:int = 1;
		/**
		 * 指定其它对象是否可以经过所占的位置,默认为可以。
		 * 可以动态改变一个物件的通行属性，动态改变物件的属性可以完成一个物件根据状态进行通行的功能，如开启的和关闭的门
		 */
		public function set walkable(value:int):void
		{
			_walkable = value;
			statusChangeMark();//如果改变walkable需要重新添加当前物件改便使walkable生效
		}
		public function get walkable():int
		{
			return _walkable;
		}
		
		
		//标记当前影响渲染的状态改变
		private function statusChangeMark():void
		{
			if(this.parentWorld)
			{
				this.parentWorld.markChange(this);
			}
		}
		
		/**
		 * 设置物件的活跃状态
		 */
		public function frozen():void
		{
			
		}
		
		
		/**
		 * 释放物件的内存占用，停止一切逻辑执行
		 */
		public function dispose():void
		{
			
		}
		
		
		
		private var _parentWorld:IsoWorld;
		/**
		 * 当前对象所属于的父级世界
		 */
		public function set parentWorld(value:IsoWorld):void
		{
			_parentWorld = value;
			
			if(_parentWorld != null)
			{
				_size = _parentWorld.size;
				_isoPositionChanged = true;//如果对象被添加到别处则需要重新被计算
			}
		}
		public function get parentWorld():IsoWorld
		{
			return _parentWorld;
		}
		
		override public function render():void
		{
			super.render();
//			trace("IsoObjectXY::::::",this.x,this.y);
		}
	}
}